package com.github.ggeorgovassilis.springjsonmapper.jaxrs; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.CookieParam; import javax.ws.rs.DELETE; import javax.ws.rs.FormParam; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.HttpMethod; import com.github.ggeorgovassilis.springjsonmapper.model.MappingDeclarationException; import com.github.ggeorgovassilis.springjsonmapper.model.MethodParameterDescriptor; import com.github.ggeorgovassilis.springjsonmapper.model.UrlMapping; import com.github.ggeorgovassilis.springjsonmapper.model.MethodParameterDescriptor.Type; import com.github.ggeorgovassilis.springjsonmapper.spring.BaseAnnotationMethodInspector; /** * Looks at methods and extracts {@link Path}, {@link GET}, {@link QueryParam} * etc annotations * * @author george georgovassilis * */ public class JaxRsAnnotationMethodInspector extends BaseAnnotationMethodInspector { /* * RequestMapping -> PATH, GET, POST RequestParam -> QueryParam PathVariable * -> PathParam RequestBody -> BeanParam RequestPart -> FormParam */ @Override public UrlMapping inspect(Method method, Object[] args) { UrlMapping urlMapping = new UrlMapping(); Path path = AnnotationUtils.findAnnotation(method, Path.class); if (path == null || path.value() == null) return null; urlMapping.setUrl(resolveExpression(path.value())); if (urlMapping.getUrl() == null) throw new MappingDeclarationException( "Missing @Path on method " + method, method, path, -1); Set<HttpMethod> httpMethods = new HashSet<>(); if (AnnotationUtils.findAnnotation(method, POST.class) != null) httpMethods.add(HttpMethod.POST); if (AnnotationUtils.findAnnotation(method, PUT.class) != null) httpMethods.add(HttpMethod.PUT); if (AnnotationUtils.findAnnotation(method, DELETE.class) != null) httpMethods.add(HttpMethod.DELETE); if (httpMethods.size()>1) throw new MappingDeclarationException("Multiple HTTP methods specified on "+method.toGenericString(), method, null, -1); if (httpMethods.size()==1) urlMapping.setHttpMethod(httpMethods.iterator().next()); else urlMapping.setHttpMethod(HttpMethod.GET); Produces produces = AnnotationUtils.findAnnotation(method, Produces.class); if (produces != null) urlMapping.setProduces(produces.value()); Consumes consumes = AnnotationUtils.findAnnotation(method, Consumes.class); if (consumes != null) urlMapping.setConsumes(consumes.value()); Annotation[][] parameterAnnotations = method.getParameterAnnotations(); if (parameterAnnotations.length != method.getParameterTypes().length) throw new MappingDeclarationException( String.format( "Annotation mismatch: method has %d parameters but %d have been annotated on %s", parameterAnnotations.length, method.getParameterTypes().length, method.toString()),method, null, -1); int i = 0; for (Annotation[] annotations : parameterAnnotations) { Object value = args[i]; i++; String parameterName = ""; Type parameterType = null; boolean parameterFound = false; for (Annotation annotation : annotations) { if (PathParam.class.isAssignableFrom(annotation.annotationType())) { PathParam pv = (PathParam) annotation; parameterName = pv.value(); urlMapping.addDescriptor(new MethodParameterDescriptor( Type.pathVariable, parameterName, value, method, i)); parameterFound = true; } if (QueryParam.class.isAssignableFrom(annotation .annotationType())) { QueryParam pv = (QueryParam) annotation; parameterName = pv.value(); urlMapping.addDescriptor(new MethodParameterDescriptor( Type.httpParameter, parameterName, value, method, i)); parameterFound = true; } if (HeaderParam.class.isAssignableFrom(annotation .annotationType())) { HeaderParam pv = (HeaderParam) annotation; parameterName = pv.value(); parameterFound = true; parameterType = Type.httpHeader; } if (BeanParam.class.isAssignableFrom(annotation .annotationType())) { parameterType = Type.requestBody; parameterFound = true; } if (FormParam.class.isAssignableFrom(annotation .annotationType())) { parameterType = Type.requestPart; parameterFound = true; } if (CookieParam.class.isAssignableFrom(annotation .annotationType())) { parameterType = Type.cookie; parameterFound = true; CookieParam cv = (CookieParam) annotation; parameterName = cv.value(); } } if (!parameterFound) throw new MappingDeclarationException( String.format( "Couldn't find mapping annotation on parameter %d of method %s", i, method.toGenericString()), method, null, i); if (parameterType != null) { urlMapping.addDescriptor(new MethodParameterDescriptor( parameterType, parameterName, value, method, i)); } } return urlMapping; } }